Run-Time Type Information (RTTI)
In normal cases the type of any variable can be determined at compile time, for
example if we write this declaration:
var
Count: Integer;
The compiler will know the fact that Count is of integer type, so that if we try
to assign string to Count, compile time error will be generated (Type mismatch):
Count:= 'Hello';
At run time we can not check type of any variable, bacause the type of variable
cann't be changed or used for more than one type.
Object Oriented Programming in Delphi introduces new method of run-time type checking
using as and is operators. As you might know any object reference can be used to
hold any object of the same type as well as descendant types, for example:
var
MyObject: TControl;
begin
MyObject:= Button1;
MyObject:= Form1;
TControl class is the anscestor class for all Delphi controls such as forms, buttons,
edit boxes and so on, so that we can assign any control to MyObject variable. Look
for TButton and TForm hierarchy:
TButton hierarchy:
TObject
|
TPersistent
|
TComponent
|
TWinControl
|
TButtonControl
|
TButton
TForm hierarchy:
TObject
|
TPersistent
|
TComponent
|
TControl
|
TWinControl
|
TScrollingWinControl
|
TCustomForm
|
TForm
As you have seen, TForm and TButton share TControl anscestor. Another important
fact that the TObject is the parent class for any Delphi class even if you do not
explicity inherit it, for example if you define three class such as:
type
TFirst = Class(TObject)
.....
TSecond = Class(TForm)
.....
TThird = Class
...
In above example TFirst declared as a direct descendant of TObject class. TSecond declared
as direct descendant of TForm, because TForm was inherits TObject class so that TObject
class will be inherited by TSecond class. TThird class declared without any explicit
anscestor so that Delphi - by default - will assume that TObject is the anscestor
of TThird class. The below declarations in Delphi would be the same:
TThird = Class
.....
TThird = Class(TObject)
.....
IS operator
IS operator used to chech if an object reference to certain type, such as:
if (MyObject is TForm) then
....
as returns true if MyObject is a TForm object or any TForm descendant such as:
type
TMyForm = class (TForm)
....
var
MyForm: TMyForm;
Form1: TForm;
begin
MyForm:= TForm.Create(Self);
Form1:= TForm.Create(Self);
if (MyForm is TForm) then...
if (Form1 is TForm) then....
if (Myform is TMyForm) then..
if (MyForm is TObject) then..
Above four if statements will return true.
AS operator
as operator used to typecast object to any desired object type such as:
MyObject as TButton
That mean we treat MyObject as a Button, for example we can access any button properties
and methods such as:
(MyObject as TButton).Caption:= 'E&xit';
Instead of using as operator we can explicty typecast objects using class type such
as:
TButton(MyObject).Caption:= 'E&xit';
Note:
Befor you typecast any object to another type make sure that the object reference
to desired object type or one of it's anscestors, if not; run-time error will be
generated. For example below statements are valid:
var
MyObject: TObject;
MyButton: TButton;
begin
MyObject:= Form1;
TForm(MyObject).WindowState:= wsMaximized;
(MyObject as TForm).Caption:= 'Test';
MyObject:= Button1;
TButton(MyObject).Caption:= 'E&xit';
MyButton:= Button1;
(MyButton as TObject).Name:= 'Button1';
end;
Below statements are invalid (appear in red color):
var
MyObject: TObject;
MyButton: TButton;
begin
MyObject:= Form1;
MyButton:= Button1;
TForm(MyButton).Caption:= 'Invalid typecst';
(MyObject as TButton).Caption:= 'Test';
end;
Example
1. Drop three Buttons, an Edit box, a Memo, and a ListBox.
2. Select all these components and double click at OnClick event for all of them,
(make sure that you write one event for all above component and share this event
for all componets)
3. At selected OnClick event write:
procedure TForm1.Button1Click(Sender: TObject);
begin
if Sender is TButton then
ShowMessage('This is a Button '+#10+
(Sender as TButton).Caption)
else
if Sender is TEdit then
ShowMessage('This is an Edit box'+#10+
(Sender as TEdit).Text)
else
if Sender is TMemo then
ShowMessage('This is a Memo'+#10+
(Sender as TMemo).Text)
else
if Sender is TCheckBox then
ShowMessage('This is a CheckBox'+#10+
(Sender as TCheckBox).Caption);
end;
See also:
Creating components at run-time